package de.akad.imp03.client.ui;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.google.gwt.cell.client.ActionCell;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.text.client.LongParser;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.IdentityColumn;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

import de.akad.imp03.client.service.DaoService;
import de.akad.imp03.client.service.DaoServiceAsync;
import de.akad.imp03.shared.PersonObjectify;

public class PersonGUI implements EntryPoint {

	private final DaoServiceAsync daoService = GWT.create(DaoService.class);

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
	    final ProvidesKey<PersonObjectify> KEY_PROVIDER = new ProvidesKey<PersonObjectify>() {
	        public Object getKey(PersonObjectify p) {
	          return p == null ? null : p.getId();
	        }
	    };
		final ListDataProvider<PersonObjectify> dataProvider = new ListDataProvider<PersonObjectify>(KEY_PROVIDER);
		final CellTable<PersonObjectify> table = new CellTable<PersonObjectify>();
		dataProvider.addDataDisplay(table);

		final Label idLabel = new Label("Id:");
		final Label vornameLabel = new Label("Vorname:");
		final Label nachnameLabel = new Label("Nachname:");
		final Label gebdatLabel = new Label("Geburtsdatum (TT.MM.JJJJ)");
		final TextBox idField = new TextBox();
		idField.setReadOnly(true);
		final TextBox vornameField = new TextBox();
		final TextBox nachnameField = new TextBox();
		final TextBox gebdatField = new TextBox();
		final Grid detailTable = new Grid(4,2);
		detailTable.setWidget(0, 0, idLabel);
		detailTable.setWidget(0, 1, idField);
		detailTable.setWidget(1, 0, vornameLabel);
		detailTable.setWidget(1, 1, vornameField);
		detailTable.setWidget(2, 0, nachnameLabel);
		detailTable.setWidget(2, 1, nachnameField);
		detailTable.setWidget(3, 0, gebdatLabel);
		detailTable.setWidget(3, 1, gebdatField);
		
		final HTML detailHeading = new HTML("<h1>Details bearbeiten</h1>");
		final Label errorLabel = new Label();
		VerticalPanel detailPanel = new VerticalPanel();
		detailPanel.add(detailHeading);
		detailPanel.add(errorLabel);
		detailPanel.add(detailTable);
		
		final Button saveButton = new Button("Save");
		final Button newButton = new Button("New");
		final Button cancelButton = new Button("Cancel");
		HorizontalPanel detailButtons = new HorizontalPanel();
		detailButtons.add(saveButton);
		detailButtons.add(newButton);
		detailButtons.add(cancelButton);
		detailPanel.add(detailButtons);
		RootPanel.get("detailPanel").add(detailPanel);

		
		TextColumn<PersonObjectify> vornameCol = new TextColumn<PersonObjectify>() {
	        @Override
	        public String getValue(PersonObjectify p) {
	          return p.getVorname();
	        }
	    };
	    table.addColumn(vornameCol, "Vorname");

		TextColumn<PersonObjectify> nachnameCol = new TextColumn<PersonObjectify>() {
		    @Override
		    public String getValue(PersonObjectify p) {
		      return p.getNachname();
		    }
		};
		table.addColumn(nachnameCol, "Nachname");
		
	    DateCell dateCell = new DateCell(DateTimeFormat.getFormat("dd.MM.yyyy"));
	    Column<PersonObjectify, Date> dateCol = new Column<PersonObjectify, Date>(dateCell) {
	      @Override
	      public Date getValue(PersonObjectify p) {
	        return p.getGeburtsdatum();
	      }
	    };
	    table.addColumn(dateCol, "Geburtsdatum");
	
	    ActionCell<PersonObjectify> editCell = new ActionCell<PersonObjectify>("Edit", 
		    	new ActionCell.Delegate<PersonObjectify>() {
		    	
		        @Override
		        public void execute(PersonObjectify p) {
		          //Window.alert("You clicked " + p.getNachname());
		        }
		    });
		    IdentityColumn<PersonObjectify> editCol = new IdentityColumn<PersonObjectify>(editCell);
		    table.addColumn(editCol, "Edit");

	    ActionCell<PersonObjectify> delCell = new ActionCell<PersonObjectify>("Delete", 
		    	new ActionCell.Delegate<PersonObjectify>() {
		    	
		        @Override
		        public void execute(PersonObjectify p) {
					daoService.deletePerson(p, new AsyncCallback<Boolean>() {
						@Override
						public void onSuccess(Boolean result) {
							if (result)
								Window.alert("Delete successful!");
							refresh(dataProvider);
						}
						
						@Override
						public void onFailure(Throwable caught) {
							GWT.log("onFailure: " + caught.getMessage(), caught);
						}
					});
					idField.setText("");
					vornameField.setText("");
					nachnameField.setText("");
					gebdatField.setText("");
		        }
		    });
		    IdentityColumn<PersonObjectify> delCol = new IdentityColumn<PersonObjectify>(delCell);
		    table.addColumn(delCol, "Delete");

		refresh(dataProvider);
		
		final HTML tableHeading = new HTML("<h1>Personen verwalten</h1>");
		final Button refreshButton = new Button("Refresh");
		final Button importButton = new Button("Import");
		final Button exportButton = new Button("Export");
		final HorizontalPanel tableButtons = new HorizontalPanel();
		tableButtons.add(refreshButton);
		tableButtons.add(importButton);
		tableButtons.add(exportButton);
		final VerticalPanel tablePanel = new VerticalPanel();
		tablePanel.add(tableHeading);
		tablePanel.add(tableButtons);
		tablePanel.add(table);
		RootPanel.get("personTable").clear();
		RootPanel.get("personTable").add(tablePanel);
		
	    final SingleSelectionModel<PersonObjectify> selectionModel = new SingleSelectionModel<PersonObjectify>();
	    table.setSelectionModel(selectionModel);
	    selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
	      @Override
	      public void onSelectionChange(SelectionChangeEvent event) {
	        PersonObjectify selected = selectionModel.getSelectedObject();
	        if (selected == null) {
				idField.setText("");
				vornameField.setText("");
				nachnameField.setText("");
				gebdatField.setText("");
	        } else {
	        	idField.setText("" + selected.getId());
	        	vornameField.setText(selected.getVorname());
	        	nachnameField.setText(selected.getNachname());
	        	if (selected.getGeburtsdatum() == null) {
	        		gebdatField.setText("");
	        	} else {
	        		gebdatField.setText(DateTimeFormat.getFormat("dd.MM.yyyy").format(selected.getGeburtsdatum()));
	        	}
	    		vornameField.setFocus(true);
	    		vornameField.selectAll();
	        }
	      }
	    });


		class SaveHandler implements ClickHandler {
			/**
			 * Fired when the user clicks on the sendButton.
			 */
			public void onClick(ClickEvent event) {
				GWT.log("SaveHandler start.");
//		        PersonObjectify selected = selectionModel.getSelectedObject();
//		        selectionModel.setSelected(selected, false);
		        PersonObjectify p = new PersonObjectify();
		        try {
					p.setId(LongParser.instance().parse(idField.getText()));
				} catch (ParseException e) {
					p.setId(null);
				}
				p.setVorname(vornameField.getText());
				p.setNachname(nachnameField.getText());
				try {
					String text = gebdatField.getText();
					p.setGeburtsdatum(DateTimeFormat.getFormat("dd.MM.yyyy").parse(text));
					daoService.savePerson(p, new AsyncCallback<Long>() {
								
						@Override
						public void onSuccess(Long result) {
							GWT.log("savePerson: " + result);
							refresh(dataProvider);
						}
						
						@Override
						public void onFailure(Throwable caught) {
							Window.alert("onFailure: " + caught.getMessage());
						}
					});
					idField.setText("");
					vornameField.setText("");
					nachnameField.setText("");
					gebdatField.setText("");
					Window.alert("Save successful!");
				} catch (IllegalArgumentException e) {
					Window.alert("Datumsformat nicht korrekt!");
				}
				GWT.log("SaveHandler end.");
			}

		}

		class NewHandler implements ClickHandler {
			/**
			 * Fired when the user clicks on the sendButton.
			 */
			public void onClick(ClickEvent event) {
				GWT.log("SaveHandler start.");
//		        PersonObjectify selected = selectionModel.getSelectedObject();
//		        selectionModel.setSelected(selected, false);
		        PersonObjectify p = new PersonObjectify();
				p.setId(null);
				p.setVorname(vornameField.getText());
				p.setNachname(nachnameField.getText());
				try {
					String text = gebdatField.getText();
					p.setGeburtsdatum(DateTimeFormat.getFormat("dd.MM.yyyy").parse(text));
					daoService.savePerson(p, new AsyncCallback<Long>() {
								
						@Override
						public void onSuccess(Long result) {
							GWT.log("newPerson: " + result);
							refresh(dataProvider);
						}
						
						@Override
						public void onFailure(Throwable caught) {
							Window.alert("onFailure: " + caught.getMessage());
						}
					});
					idField.setText("");
					vornameField.setText("");
					nachnameField.setText("");
					gebdatField.setText("");
					Window.alert("New successful!");
				} catch (IllegalArgumentException e) {
					Window.alert("Datumsformat nicht korrekt!");
				}
				GWT.log("NewHandler end.");
			}

		}

		class CancelHandler implements ClickHandler {
			/**
			 * Fired when the user clicks on the sendButton.
			 */
			public void onClick(ClickEvent event) {
				GWT.log("CancelHandler start.");
				idField.setText("");
				vornameField.setText("");
				nachnameField.setText("");
				gebdatField.setText("");
			}

		}

		class ExportHandler implements ClickHandler {
			@Override
			public void onClick(ClickEvent event) {
				GWT.log("ExportHandler start.");
				daoService.findAllPersons(new AsyncCallback<List<PersonObjectify>>() {
					@Override
					public void onSuccess(List<PersonObjectify> list) {
						ArrayList<String> result = new ArrayList<String>();
						result.add("\"id\";\"vorname\";\"nachname\";\"geburtsdatum\"");
						for (PersonObjectify pers: list) {
							if (pers != null) {
								result.add("\"" + pers.getId() == null ? "":pers.getId()  + "\";"
										+ "\"" + pers.getVorname() == null ? "": pers.getVorname() + "\";"
										+ "\"" + pers.getNachname() == null ? "": pers.getNachname() + "\";"
										+ "\"" + pers.getGeburtsdatum() == null ? "": DateTimeFormat.getFormat("dd.MM.YYYY").format(pers.getGeburtsdatum()) + "\""
								);
							}
						}
					}
					
					@Override
					public void onFailure(Throwable caught) {
						GWT.log("onFailure: " + caught.getMessage(), caught);
					}
				});
			}

		}

		class RefreshHandler implements ClickHandler {
			/**
			 * Fired when the user clicks on the sendButton.
			 */
			public void onClick(ClickEvent event) {
				GWT.log("RefreshHandler start.");
				refresh(dataProvider);
			}

		}

		saveButton.addClickHandler(new SaveHandler());
		newButton.addClickHandler(new NewHandler());
		cancelButton.addClickHandler(new CancelHandler());
		refreshButton.addClickHandler(new RefreshHandler());
	}

	protected void refresh(final ListDataProvider<PersonObjectify> dataProvider) {
		daoService.findAllPersons(new AsyncCallback<List<PersonObjectify>>() {
			@Override
			public void onSuccess(List<PersonObjectify> result) {
				dataProvider.setList(result);
				dataProvider.refresh();
			}
			
			@Override
			public void onFailure(Throwable caught) {
				GWT.log("onFailure: " + caught.getMessage(), caught);
			}
		});
		
		
	}
}
	
	
